package com.dhcc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dhcc.base.BaseServiceImpl;
import com.dhcc.entity.SysDept;
import com.dhcc.httpApiService.IdGeneratorService;
import com.dhcc.mapper.SysDeptMapper;
import com.dhcc.service.SysDeptService;
import com.dhcc.service.SysUserService;
import com.dhcc.utils.DeptTreeBuilder;
import com.dhcc.response.SysDeptListTree;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 部门表接口实现类
 * @ProjectName Dhcc-Cloud
 * @PackageName com.dhcc.service.impl
 * @Title SysDeptServiceImpl
 * @Date 2024/12/5 下午3:51
 * @Author LiuGuoting
 */
@Service
public class SysDeptServiceImpl extends BaseServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {
    /**
     * ID 生成器服务，用于生成唯一 ID
     */
    @Resource
    private IdGeneratorService idGeneratorService;
    /**
     *  用户接口服务
     */
    @Resource
    private SysUserService sysUserService;

    /**
     * 自定义分页
     *
     * @param page 分页参数
     * @param sysDept 部门信息对象实体
     * @return IPage<SysUser> 分页结果对象
     */
    @Override
    public IPage<SysDeptListTree> selectDeptPage(IPage<SysDept> page, SysDept sysDept) {
        // 1. 创建查询条件，查询父部门（分页）
        QueryWrapper<SysDept> sysDeptQueryWrapper = new QueryWrapper<>();
        // 模糊查询部门名称，忽略大小写
        sysDeptQueryWrapper.lambda()
                // 模糊查询部门名称，忽略大小写
                .like(StringUtils.hasText(sysDept.getDepartmentName()), SysDept::getDepartmentName, sysDept.getDepartmentName())
                // 仅查询父部门
                .isNull(SysDept::getFatherDepartmentId)
                // 只查询未删除的部门，避免返回已删除的部门（存在-0，删除-1）
                .eq(SysDept::getDelFlag, 0)
                // 按排序字段升序
                .orderByDesc(SysDept::getSort);
        // 分页查询父部门
        IPage<SysDept> parentPage = baseMapper.selectPage(page, sysDeptQueryWrapper);
        // 从分页结果中取出父部门列表，并重新设置创建用户的名称和修改用户的名称
        List<SysDept> parentDepts = parentPage.getRecords();
        for (SysDept dept : parentDepts) {
            dept.setCreateUser(sysUserService.getUserNameById(dept.getCreateUser()));
            dept.setUpdateUser(sysUserService.getUserNameById(dept.getUpdateUser()));
        }
        // 2. 查询所有部门（非分页，用于构建完整部门树）
        List<SysDept> allDepts = baseMapper.selectList(new QueryWrapper<SysDept>()
                .lambda()
                // 模糊查询部门名称，忽略大小写
                .like(StringUtils.hasText(sysDept.getDepartmentName()), SysDept::getDepartmentName, sysDept.getDepartmentName())
                // 只查询未删除的部门，避免返回已删除的部门（存在-0，删除-1）
                .eq(SysDept::getDelFlag, 0)
                // 按排序字段升序
                .orderByDesc(SysDept::getSort));
        // 遍历所有部门，重新设置创建用户的名称和修改用户的名称
        for (SysDept dept : allDepts) {
            dept.setCreateUser(sysUserService.getUserNameById(dept.getCreateUser()));
            dept.setUpdateUser(sysUserService.getUserNameById(dept.getUpdateUser()));
        }
        // 3. 构建部门树，将每个父部门附加子部门
        List<SysDeptListTree> deptTree = parentDepts.stream()
                .map(parentDept -> {
                    // 将父部门转换为 VO
                    SysDeptListTree parentDeptVO = DeptTreeBuilder.convertToVO(parentDept);
                    // 构建当前父部门的子部门树
                    List<SysDeptListTree> children = DeptTreeBuilder.buildDeptTree(
                            allDepts.stream()
                                    // 将所有部门转换为 VO
                                    .map(DeptTreeBuilder::convertToVO)
                                    .collect(Collectors.toList()),
                            parentDept.getId());
                    // 设置子部门
                    parentDeptVO.setChildren(children);
                    return parentDeptVO;
                })
                .collect(Collectors.toList());
        // 4. 构建分页对象
        IPage<SysDeptListTree> sysDeptVOIPage = new Page<>(parentPage.getCurrent(), parentPage.getSize(), parentPage.getTotal());
        // 设置树形结构的部门列表
        sysDeptVOIPage.setRecords(deptTree);
        return sysDeptVOIPage;
    }

    /**
     * 自定义查询部门树
     * @return List<SysDeptListTree> 部门树结构列表
     */
    @Override
    public List<SysDeptListTree> listDeptTree() {
        // 查询所有未删除的部门
        QueryWrapper<SysDept> sysDeptQueryWrapper = new QueryWrapper<>();
        sysDeptQueryWrapper.lambda()
                // 只查询未删除的部门，避免返回已删除的部门（存在-0，删除-1）
                .eq(SysDept::getDelFlag, 0)
                // 按排序字段升序
                .orderByDesc(SysDept::getSort);
        // 查询所有部门
        List<SysDept> allDepts = baseMapper.selectList(sysDeptQueryWrapper);
        // 重新设置创建用户的名称和修改用户的名称
        for (SysDept dept : allDepts) {
            dept.setCreateUser(sysUserService.getUserNameById(dept.getCreateUser()));
            dept.setUpdateUser(sysUserService.getUserNameById(dept.getUpdateUser()));
        }
        // 构建部门树
        return DeptTreeBuilder.buildDeptTree(allDepts, null);
    }

    /**
     * 新增部门
     * @param sysDept 部门信息
     * @return Boolean 是否成功
     */
    @Override
    public Boolean addDept(SysDept sysDept) {
        // 参数校验
        validateDeptParams(sysDept);
        // 查询跟部门中是否有同名部门
        LambdaQueryWrapper<SysDept> wrapperA = new LambdaQueryWrapper<>();
        wrapperA.eq(SysDept::getDepartmentName, sysDept.getDepartmentName());
        wrapperA.isNull(SysDept::getFatherDepartmentId);
        wrapperA.eq(SysDept::getDelFlag, 0);
        if (count(wrapperA) > 0) {
            throw new IllegalArgumentException("同名根部门已存在！");
        }
        // 查询该父部门下是否有同名部门
        LambdaQueryWrapper<SysDept> wrapperB = new LambdaQueryWrapper<>();
        wrapperB.eq(SysDept::getDepartmentName, sysDept.getDepartmentName());
        wrapperB.eq(SysDept::getFatherDepartmentId, sysDept.getFatherDepartmentId());
        wrapperB.eq(SysDept::getDelFlag, 0);
        if (count(wrapperB) > 0) {
            throw new IllegalArgumentException("该父部门下已存在同名部门！");
        }
        // 设置默认属性
        sysDept.setId(idGeneratorService.nextId().toString());
        return baseMapper.insert(sysDept) > 0;
    }

    /**
     * 更新部门
     * @param sysDept 部门信息实体对象
     * @return Boolean 是否成功
     */
    @Override
    public Boolean updateDept(SysDept sysDept) {
        // 参数校验
        validateDeptParams(sysDept);
        // 参数校验通过后，更新部门信息
        LambdaUpdateWrapper<SysDept> sysDeptLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        sysDeptLambdaUpdateWrapper.eq(SysDept::getId, sysDept.getId());
        // 返回true，表示更新成功，false表示更新失败
        return baseMapper.update(sysDept,sysDeptLambdaUpdateWrapper) > 0;
    }

    /**
     * 查询部门详情(基本信息)
     *
     * @param id 部门ID
     * @return SysDept 部门信息实体对象
     */
    @Override
    public SysDept getDeptById(String id) {
        // 创建查询条件
        LambdaQueryWrapper<SysDept> sysDeptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询条件：部门ID
        sysDeptLambdaQueryWrapper.eq(SysDept::getId, id);
        // 查询部门信息
        SysDept dept = getOne(sysDeptLambdaQueryWrapper);
        // 如果查询结果为空，则返回 null
        if (dept == null) {
            return null;
        }
        // 返回不为空，则设置创建用户的名称和修改用户的名称
        dept.setCreateUser(sysUserService.getUserNameById(dept.getCreateUser()));
        dept.setUpdateUser(sysUserService.getUserNameById(dept.getUpdateUser()));
        // 返回部门信息
        return dept;
    }

    /**
     * 启用禁用部门
     *
     * @param id 部门ID
     * @param status 部门状态，0：禁用，1：启用
     * @return  Boolean 是否成功
     */
    @Override
    public Boolean changeDeptStatus(String id, int status) {
        // 创建更新条件
        LambdaUpdateWrapper<SysDept> sysDeptLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 更新条件：部门ID，更新参数：部门状态
        sysDeptLambdaUpdateWrapper.eq(SysDept::getId, id).set(SysDept::getStatus, status);
        // 更新部门状态
        return baseMapper.update(sysDeptLambdaUpdateWrapper) > 0;
    }

    /**
     * 批量启用禁用部门
     *
     * @param ids 部门ID列表
     * @param status 部门状态，0：禁用，1：启用
     * @return Boolean 是否成功
     */
    @Override
    public Boolean changeDeptStatuss(List<String> ids, int status) {
        // 1. 参数校验
        if (ids.isEmpty() || (status != 0 && status != 1)) {
            return false;
        }
        // 2. 构建更新条件
        LambdaUpdateWrapper<SysDept> sysDeptLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 更新条件：部门ID列表，更新参数：部门状态
        sysDeptLambdaUpdateWrapper.in(SysDept::getId, ids).set(SysDept::getStatus, status);
        // 3. 更新部门状态
        return baseMapper.update(sysDeptLambdaUpdateWrapper) > 0;
    }


    /**
     * 校验新增部门的参数
     *
     * @param sysDept 部门信息
     */
    private void validateDeptParams(SysDept sysDept) {
        // 校验部门名称是否为空
        if (!StringUtils.hasText(sysDept.getDepartmentName())) {
            throw new IllegalArgumentException("部门名称不能为空");
        }
        // 校验父部门 ID 是否有效
        String fatherDepartmentId = sysDept.getFatherDepartmentId();
        if (fatherDepartmentId == null || fatherDepartmentId.trim().isEmpty()) {
            // 父部门 ID 无效，认为是根部门，直接返回
            // 明确设置为 null，防止数据库插入时出错
            sysDept.setFatherDepartmentId(null);
            return;
        }
        // 验证父部门是否存在
        LambdaQueryWrapper<SysDept> sysDeptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 根据父部门 ID 查询
        sysDeptLambdaQueryWrapper.eq(SysDept::getId, fatherDepartmentId);
        // 查询父部门
        SysDept parentDept = getOne(sysDeptLambdaQueryWrapper);
        // 判断父部门是否存在
        if (parentDept == null) {
            // 父部门不存在，抛出异常
            throw new IllegalArgumentException("父部门不存在！");
        }
        // 判断父部门是否可用，即是否被删除或禁用
        if (parentDept.getDelFlag() == 1 || parentDept.getStatus() == 1) {
            throw new IllegalArgumentException("父部门已被删除，暂不可用！");
        }
    }

}
